package cloud.maque.admin.impl;


import cloud.maque.admin.domain.consts.ConstVar;
import cloud.maque.admin.domain.entity.MqRole;
import cloud.maque.admin.domain.entity.MqUser;
import cloud.maque.admin.domain.entity.MqUserRole;
import cloud.maque.admin.domain.vo.MqCreateUserModel;
import cloud.maque.admin.domain.vo.UserUpdatePwd;
import cloud.maque.admin.domain.vo.UserVo;
import cloud.maque.admin.mapper.MqUserMapper;
import cloud.maque.admin.service.MqRoleService;
import cloud.maque.admin.service.MqUserDepartmentService;
import cloud.maque.admin.service.MqUserRoleService;
import cloud.maque.admin.service.MqUserService;
import cloud.maque.framework.common.exception.BusinessException;
import cloud.maque.framework.common.exception.CommonPassWordNoStrongException;
import cloud.maque.framework.common.request.PaginateDataResquest;
import cloud.maque.framework.common.utils.PasswordUtils;
import cloud.maque.framework.common.utils.SHAUtils;
import cloud.maque.framework.conf.PlatformConfigProperties;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * 用户管理
 */
@Service
@Slf4j
public class MqUserServiceImpl extends ServiceImpl<MqUserMapper, MqUser> implements MqUserService {


    @Autowired
    MqUserRoleService roleUserService;

    @Autowired
    MqRoleService roleService;

    @Autowired
    MqUserDepartmentService departmentService;

    @Autowired
    PasswordUtils passwordUtils;

    @Autowired
    PlatformConfigProperties conf;

    @Autowired
    MqUserExtServiceImpl extService;


    @Override
    public MqUser getUser(String userId) {
        MqUser mqUser = this.getById(userId);
        mqUser.setUserPwd("");
        return mqUser;
    }

    @Override
    @Transactional
    public MqCreateUserModel saveUser(MqCreateUserModel userModel) {

        if (userModel.getUser() == null) {
            throw new BusinessException("缺少数据");
        }

        MqUser newUser = userModel.getUser();

        if (StrUtil.isEmptyIfStr(newUser.getRegUserName().trim())) {
            throw new BusinessException("用户名不能为空");
        }

        //用户名处理
        newUser.setUserName(newUser.getTenantId() + "_" + newUser.getRegUserName());

        MqUser oldUser = this.getUserByUserName(newUser.getUserName());
        if (oldUser != null && !oldUser.getUserId().equals(newUser.getUserId())) {
            throw new BusinessException("用户名已存在");
        }

        if (oldUser != null && !oldUser.getRegUserName().equals(newUser.getRegUserName())) {
            throw new BusinessException("用户名不能修改");
        }

        /**
         * 相关数据处理
         */
        //密码处理
        if (StrUtil.isEmptyIfStr(newUser.getUserPwd())) {
            if (oldUser != null) {
                newUser.setUserPwd(oldUser.getUserPwd());
            }
        } else {
            //密码加密
            newUser.setUserPwd(SHAUtils.entryptPassword(newUser.getUserPwd()));
        }


        if (oldUser != null) {
            //租户管理员不能更改
            userModel.getUser().setIsTenantManager(oldUser.getIsTenantManager());
        } else {
            //新的都不是租户管理员
            userModel.getUser().setIsTenantManager(0);
        }
        this.saveOrUpdate(userModel.getUser());

        //先清空角色
        roleUserService.deleteByUserId(userModel.getUser().getUserId());
        if (userModel.getUserRoles() != null && userModel.getUserRoles().size() > 0) {
            userModel.getUserRoles().forEach(item -> {
                item.setUserId(userModel.getUser().getUserId());
            });
            roleUserService.AddUserRole(userModel.getUserRoles());
        }

        //先清空部门
        departmentService.deleteByUserId(userModel.getUser().getUserId());
        if (userModel.getUserDepartments() != null && userModel.getUserDepartments().size() > 0) {
            userModel.getUserDepartments().forEach(item -> {
                item.setUserId(userModel.getUser().getUserId());
            });
            departmentService.AddUserDepartment(userModel.getUserDepartments());
        }

        return userModel;
    }


    @Override
    @Transactional
    public MqCreateUserModel saveBySuperManager(MqCreateUserModel userModel) {

        if (userModel.getUser() == null) {
            throw new BusinessException("缺少数据");
        }

        MqUser newUser = userModel.getUser();

        if (StrUtil.isEmptyIfStr(newUser.getRegUserName().trim())) {
            throw new BusinessException("用户名不能为空");
        }

        //用户名处理
        newUser.setUserName(newUser.getTenantId() + "_" + newUser.getRegUserName());

        MqUser oldUser = this.getUserByUserName(newUser.getUserName());
        if (oldUser != null && !oldUser.getUserId().equals(newUser.getUserId())) {
            throw new BusinessException("用户名已存在");
        }

        if (oldUser != null && !oldUser.getRegUserName().equals(newUser.getRegUserName())) {
            throw new BusinessException("用户名不能修改");
        }

        /**
         * 相关数据处理
         */
        //密码处理
        if (StrUtil.isEmptyIfStr(newUser.getUserPwd())) {
            if (oldUser != null) {
                newUser.setUserPwd(oldUser.getUserPwd());
            }
        } else {
            //密码加密
            newUser.setUserPwd(SHAUtils.entryptPassword(newUser.getUserPwd()));
        }

        this.saveOrUpdate(userModel.getUser());

        return userModel;
    }


    @Override
    public MqCreateUserModel getUserAllInfo(String userId) {

        MqCreateUserModel userModel = new MqCreateUserModel();

        MqUser user = getById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        userModel.setUser(user);

        userModel.setUserRoles(roleUserService.GetUserRoles(userId));

        userModel.setUserDepartments(departmentService.GetDepartments(userId));


        userModel.getUser().setUserPwd("");

        return userModel;
    }

    @Override
    public MqUser getUserByEmail(String email) {
        QueryWrapper<MqUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(MqUser::getEmail, email);
        return this.getOne(queryWrapper, false);
    }

    /**
     * 用户名的组成：租户ID+注册用户名
     *
     * @param userName
     * @return
     */
    @Override
    public MqUser getUserByUserName(String userName) {
        QueryWrapper<MqUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(MqUser::getUserName, userName);
        return this.getOne(queryWrapper, false);
    }

    @Override
    public MqUser getUserByMobile(String mobile) {
        QueryWrapper<MqUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(MqUser::getMobile, mobile);
        return this.getOne(queryWrapper, false);
    }


    @Override
    public PageInfo<MqUser> pageList(PaginateDataResquest<UserVo> qr) {

        if (qr.getPageIndex() > 0 && qr.getPageSize() > 0) {
            PageHelper.startPage(qr.getPageIndex(), qr.getPageSize());
        }

        QueryWrapper<MqUser> queryWrapper = new QueryWrapper<>();
        if (qr.getData() != null) {
            if (!StrUtil.isEmptyIfStr(qr.getData().getTenantId())) {
                queryWrapper.lambda().eq(MqUser::getTenantId, qr.getData().getTenantId());
            } else {
                queryWrapper.lambda().eq(MqUser::getTenantId, ConstVar.NoObject);
            }
            if (!StrUtil.isEmptyIfStr(qr.getData().getUserName())) {
                queryWrapper.lambda().or().like(MqUser::getUserName, qr.getData().getUserName());
            }
            if (!StrUtil.isEmptyIfStr(qr.getData().getDeptId()) && !qr.getData().getDeptId().equals("0")) {
                queryWrapper.and(q -> {
                    q.inSql("user_id", "select user_id from mq_user_department where dept_id = '" + qr.getData().getDeptId() + "'");
                });
            }
        } else {
            queryWrapper.lambda().eq(MqUser::getTenantId, ConstVar.NoObject);
        }

        List<MqUser> list = this.baseMapper.selectList(queryWrapper);

        PageInfo pageInfo = new PageInfo<>(list);

        return pageInfo;
    }

    /**
     * 删除用户时，要删除：用户表，用户扩展表
     *
     * @param id
     * @return
     */
    @Override
    @Transactional
    public Boolean delete(String id, String tenantId) {


        QueryWrapper<MqUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(MqUser::getTenantId, tenantId);
        queryWrapper.lambda().eq(MqUser::getUserId, id);

        MqUser user = getOne(queryWrapper);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        if (user.getIsTenantManager().equals(1)) {
            throw new BusinessException("租户管理员不能被删除");
        }
        Boolean ret = this.remove(queryWrapper);

        if (ret) {
            extService.deleteUser(id);

            //还有删除的更多的表

        }
        return ret;
    }

    @Override
    public Boolean UpdatePwd(UserUpdatePwd userUpdatePwd) {
        Assert.hasText(userUpdatePwd.getUserId(), "userId 不能为空");

        if (!userUpdatePwd.getPassword().trim().equals(userUpdatePwd.getPassword2().trim())) {
            throw new RuntimeException("两次旧密码不一致");
        }

        if (userUpdatePwd.getPassword().trim().equals(userUpdatePwd.getNewPassword().trim())) {
            throw new RuntimeException("新密码不能与原密码一样");
        }

        MqUser user = getUser(userUpdatePwd.getUserId());
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }


        //检查原密码是否
        try {
            Boolean isMath = passwordUtils.Verify(userUpdatePwd.getPassword().trim(), user.getUserPwd());
            if (isMath == false) {
                throw new RuntimeException("原密码不正确");
            }
        } catch (CommonPassWordNoStrongException ex) {
            //原密码不要求强度检查
        }

        String rawPassword = userUpdatePwd.getNewPassword().trim();
        //如果前端加密，这里要解密后再对比
        if (conf.getSecurity().getPassword().isEnableEncrypted()) {
            rawPassword = String.valueOf(SecureUtil.aes(conf.getSecurity().getPassword().getEncryptedKey().getBytes(StandardCharsets.UTF_8)).decrypt(userUpdatePwd.getNewPassword()));
        }
        //密码强度检查
        passwordUtils.VerifyStrong(rawPassword);

        //新密码检查
        String entryPwd = SHAUtils.entryptPassword(rawPassword);

        user.setUserPwd(entryPwd);
        user.setLastModiyPwdTime(new Date());

        return updateById(user);
    }

    /**
     * 由管理员设置用户的状态
     *
     * @param userId
     * @return
     */
    @Override
    public Boolean ChangeState(String userId) {

        Assert.hasText(userId, "userId 不能为空");
        MqUser user = getUser(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        user.setDisabled(user.getDisabled().equals(1) ? 0 : 1);
        return this.updateById(user);
    }

    @Override
    public List<List<String>> getUserRoleTree(String userId) {

        List<List<String>> tree = new ArrayList<>();
        List<MqUserRole> roles = roleUserService.GetUserRoles(userId);
        if (roles == null || roles.size() == 0) {
            return new ArrayList<>();
        }
        List<String> rolesS = new ArrayList<>();
        roles.forEach(item -> {
            rolesS.add(item.getRoleId());
        });

        List<MqRole> mqRoles = roleService.getDetails(rolesS);

        mqRoles.forEach(item -> {
            List<String> sub = new ArrayList<>();
            sub.add(item.getRoleGroupId());
            sub.add(item.getRoleId());
            tree.add(sub);
        });

        return tree;
    }

}




